package com.water.tao.util;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder;
import org.apache.hc.client5.http.ssl.TrustAllStrategy;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.pool.PoolStats;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

public class HttpClientUtil {
    static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
    private static CloseableHttpClient httpClient;
    private static HttpClientConnectionManager connectionManager;

    // 最大连接数
    private static final int MAX_TOTAL_CONNECTIONS = 200;
    // 每个路由的最大连接数（针对同一IP/Host的连接数）
    private static final int MAX_CONNECTIONS_PER_ROUTE = 50;
    // 连接超时时间 (ms)
    private static final int CONNECT_TIMEOUT_MS = 5000;
    // 请求超时时间 (ms)，从连接池获取连接的超时时间
    private static final int REQUEST_TIMEOUT_MS = 2000;
    // Socket 读取超时时间 (ms)
    private static final int SOCKET_TIMEOUT_MS = 10000;
    // 连接空闲过期时间 (ms)，连接在连接池中保持空闲的最长时间，过期会被清理
    private static final long IDLE_CONNECTION_EXPIRE_TIME_MS = 60000; // 60秒

    static {
        try {
            // 信任所有SSL证书（生产环境请根据实际情况配置，不要直接信任所有）
            SSLContext sslContext = SSLContexts.custom()
                    .loadTrustMaterial(TrustAllStrategy.INSTANCE)
                    .build();

            connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                    .setSSLSocketFactory(SSLConnectionSocketFactoryBuilder.create()
                            .setSslContext(sslContext)
                            .build())
                    .setMaxConnTotal(MAX_TOTAL_CONNECTIONS) // 最大连接数
                    .setMaxConnPerRoute(MAX_CONNECTIONS_PER_ROUTE) // 每个路由的最大连接数
                    // 连接在连接池中保持空闲的最长时间
                    .setConnectionTimeToLive(TimeValue.ofMilliseconds(IDLE_CONNECTION_EXPIRE_TIME_MS))
                    .build();

            httpClient = HttpClients.custom()
                    .setConnectionManager(connectionManager)
                    // 请求配置，包括连接、请求和Socket超时
                    .setDefaultRequestConfig(org.apache.hc.client5.http.config.RequestConfig.custom()
                            .setConnectTimeout(Timeout.ofMilliseconds(CONNECT_TIMEOUT_MS))
                            .setConnectionRequestTimeout(Timeout.ofMilliseconds(REQUEST_TIMEOUT_MS))
                            .setResponseTimeout(Timeout.ofMilliseconds(SOCKET_TIMEOUT_MS))
                            .build())
                    // 后台线程定期清理过期和空闲连接
                    .evictExpiredConnections()
                    .evictIdleConnections(TimeValue.ofMilliseconds(IDLE_CONNECTION_EXPIRE_TIME_MS))
                    .build();

            // 注册一个JVM关闭钩子，确保应用程序关闭时关闭HttpClient
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                try {
                    if (httpClient != null) {
                        httpClient.close();
                        logger.info("HttpClient connection pool closed gracefully.");
                    }
                } catch (IOException e) {
                    logger.info("Error closing HttpClient: " + e.getMessage());
                }
            }));

        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
            logger.info("Failed to initialize HttpClient connection pool: " + e.getMessage());
            e.printStackTrace();
            throw new RuntimeException("Failed to initialize HttpClient connection pool", e);
        }
    }

    /**
     * 获取配置好的 HttpClient 实例。
     * 客户端调用此方法获取 HttpClient 来执行请求。
     *
     * @return CloseableHttpClient 实例
     */
    public static CloseableHttpClient getHttpClient() {
        return httpClient;
    }

    /**
     * 获取连接池统计信息。
     *
     * @return PoolStats 连接池统计对象
     */
    public static PoolStats getConnectionPoolStats() {
        if (connectionManager instanceof org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager) {
            return ((org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager) connectionManager).getTotalStats();
        }
        return null;
    }

    /**
     * 示例：执行一个 GET 请求
     *
     * @param url 请求 URL
     * @return 响应体字符串
     * @throws IOException
     * @throws ParseException
     */
    public static String doGet(String url) throws IOException, ParseException {
        HttpGet httpGet = new HttpGet(url);
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity entity = response.getEntity();
            String responseBody = EntityUtils.toString(entity);
            System.out.println("GET Request Status: " + new StatusLine(response));
            return responseBody;
        }
    }

    /**
     * 示例：执行一个 POST 请求 (此处仅为示例，未添加请求体)
     *
     * @param url 请求 URL
     * @return 响应体字符串
     * @throws IOException
     * @throws ParseException
     */
    public static String doPost(String url) throws IOException, ParseException {
        HttpPost httpPost = new HttpPost(url);
        // httpPost.setEntity(new StringEntity("your request body", ContentType.APPLICATION_JSON)); // 如果有请求体
        try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
            HttpEntity entity = response.getEntity();
            String responseBody = EntityUtils.toString(entity);
            return responseBody;
        }
    }

    /*public static void main(String[] args) throws InterruptedException {
        // 简单测试
        String testUrl = "https://www.baidu.com"; // 请确保这是一个可访问的URL

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    String result = HttpClientUtil.doGet(testUrl);
                    // System.out.println("Thread " + Thread.currentThread().getId() + " - Result: " + result.substring(0, Math.min(result.length(), 100)) + "..."); // 打印部分结果
                } catch (IOException | ParseException e) {
                    logger.info("Thread " + Thread.currentThread().getId() + " - Request failed: " + e.getMessage());
                }
            }).start();
        }

        TimeUnit.SECONDS.sleep(5); // 等待请求完成

        // 打印连接池统计信息
        PoolStats stats = HttpClientUtil.getConnectionPoolStats();
        if (stats != null) {
            System.out.println("\nConnection Pool Stats:");
            System.out.println("  Available Connections: " + stats.getAvailable());
            System.out.println("  Leased Connections: " + stats.getLeased());
            System.out.println("  Pending Connections: " + stats.getPending());
            System.out.println("  Max Connections: " + stats.getMax());
        }

        // 注意：在实际应用中，HttpClient的关闭应该在应用程序退出时由JVM关闭钩子处理。
        // 为了演示，这里不手动关闭。
        // 如果没有JVM钩子，或者需要在特定事件时关闭，可以手动调用 httpClient.close();
    }*/
}
